<?php


namespace App\Order\Service\Order;

use App\Common\Constants\ErrorCode;
use App\Common\Service\Generator;
use App\Order\Model\CiticDataModel;
use App\Order\Model\EntrustOrderGoodsModel;
use App\Order\Model\EntrustOrderModel;
use App\Order\Model\KzRefundLogModel;
use App\Order\Model\OrderGoodsModel;
use App\Order\Model\OrderModel;
use App\Order\Model\OrderRefundModel;
use App\Order\Model\RefundGoodsModel;
use App\Order\Model\TemplateWidgetModel;
use App\Order\Model\WidgetModel;
use App\Order\Model\WxRefundLogModel;
use App\Resource\Model\GoodsModel;
use App\Resource\Model\ShopModel;
use App\Resource\Service\Cart\CartBusinessService;
use App\Resource\Service\GoodsService;
use App\Resource\Service\ShopService;
use App\Order\Service\OrderRefund\OrderRefundService;
use App\Resource\Service\TeamLeaderService;
use App\Third\Service\Lsy\LsyShopGoodsPriceService;
use App\User\Model\MemberModel;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use App\Common\Constants\Stakeholder;
use Hyperf\Utils\Context;
use Hyperf\Utils\Str;

class OrderBusinessService extends OrderBaseService implements OrderServiceInterface
{

    /**
     * @Inject()
     * @var OrderRefundService
     */
    private $orderRefundService;

    /**
     * 商家订单列表
     * @param array $where
     * @param int $limit
     * @return mixed
     */
    public function getList(array $where=[], $limit=0)
    {
        $result = [];
        $list = OrderModel::query()->where($where)->orderBy('create_at', 'desc')->paginate($limit);
        foreach ($list as $v) {
            $_data['create_at'] = $v->create_at;
            $_data['delivery_method'] = $v['deal_type'];
            $_data['delivery_method_cn'] = $this->deliveryMethod[$v['deal_type']];
            $_data['status'] = $v->status;
            $_data['deal_type'] = $v->deal_type;
            if ($v['deal_type'] == 1) {
                $_data['status_name'] = $this->deliveryOrderStatusNames[$v['status']];
                $_data['username'] = $v->address->username;
                $_data['phone'] = $v->address->phone;
                $_data['city'] = $v->address->city;
                $_data['area'] = $v->address->area;
                $_data['address'] = $v->address->address;
            } else {
                $_data['status_name'] = $this->selfTakeOrderStatusName[$v['status']];
                $_data['username'] = $v->member->nickname;
                $_data['phone'] = $v->member->phone;
                $_data['city'] = '';
                $_data['area'] = '';
                $_data['address'] = $v->shop->address;
            }
            if ($v->refund) {
                $_data['refund_status_cn'] = $this->handleStatus[$v->refund->handle_type];
            }
            $_data['shop_address'] = $v->shop->address;
            $_data['order_no'] = $v->order_no;
            $_data['serial_number'] = $v['serial_num'];
            $_data['is_group_buy'] = boolval($v['order_type'] == 6);
            $_data['pay_type'] = $this->payTypes[$v['pay_type']];
            $_data['pos_status_cn'] = $this->posTypes[$v['pos_type']];
            $_data['appointment_time'] = $v['appointment_time'];
            $result[] = $_data;
        }
        return $this->success($result, $list->total());
    }

    /**
     * 商家订单更新
     * @param array $where
     * @param array $data
     * @return bool
     */
    public function update($where = [], $data = [])
    {
        $order = $this->findFirst($where, false);
        if ($order instanceof OrderModel) {
            return $order->fill($data)->save($data);
        }
        return false;
    }
    public function delete()
    {
        // TODO: Implement delete() method.
    }
    public function findFirst($where = [], $toArray = true)
    {
        if (!$order = OrderModel::query()->where($where)->first()) {
            return null;
        }
        $toArray && $order = $order->toArray();
        return $order;
    }

    /**
     * 商家订单详情
     * @param int $shop_id
     * @param array $where
     * @return mixed
     */
    public function info($shop_id=0, $where=[]){
        if (!$order = $this->findFirst($where, false)) {
            return $this->error(ErrorCode::NOT_EXIST);
        }
        if ($order->shop_id != $shop_id) {
            return $this->error(403, '权限不足');
        }
        $statusName = $this->deliveryOrderStatusNames[$order['status']];
        if ($order['deal_type'] == self::ORDER_DEAL_TYPE_2) {
            $statusName = $this->selfTakeOrderStatusName[$order['status']];
        }
        $data = [
            'created_at'      => $order['create_at'],
            'status_cn'       => $statusName,
            'delivery_method' => $this->deliveryMethod[$order['deal_type']],
            'member'          => [
                'name'    => $order['deal_type'] == 1 ? $order->address->username : $order->member->nickname,
                'phone'   => $order['deal_type'] == 1 ? $order->address->phone : $order->member->phone,
                'address' => $order['deal_type'] == 1 ? $order->address->address : $order->shop->address,
            ],
            'order_no'        => $order['order_no'],
            'serial_number'   => $order['serial_num'],
            'pos_status_cn'   => $this->posTypes[$order['pos_type']],
            'want_take_time'  => $order['appointment_time'],
            'complete_date'   => $order['complete_date'],
            // 费用
            'goods_price'     => $order['goods_price'],
            'delivery_fee'    => $order['freight_price'],
            'coupon_amount'   => $order['coupon_cut'],
            'pay_type'        => $this->payTypes[$order['pay_type']],
            'payment_amount'  => $order['total_price'],
        ];
        // 商品列表
        $goods_list = $order->goods()
            ->select([
                Db::raw('CONCAT(goods_id,":",group_id) as only_key'),
                'goods_id',
                'group_id',
                'goods_title',
                'number',
                'dis_price',
            ])
            ->get()
            ->keyBy('only_key')
            ->toArray();
        $refund_actual_money = 0;
        // 退款信息
        $refund = new \stdClass();
        if (in_array($order->status, [5, 6, 7])) {
            $refund_no = OrderRefundModel::query()
                ->where('order_no', $order->order_no)
                ->orderBy('create_at', 'desc')
                ->value('refund_no');
            $refund_goods = RefundGoodsModel::query()->where('refund_no', $refund_no)->get([
                Db::raw('CONCAT(goods_id,":",group_id) as only_key'),
                'order_no',
                'goods_id',
                'refund_number',
            ])->keyBy('only_key')->toArray();
            foreach ($goods_list as $k => $v) {
                $goods_list[$k]['refund_number'] = $refund_goods[$k]['refund_number'] ?? 0;
            }
            $kz_refund = KzRefundLogModel::query()
                ->where('order_no', $order->order_no)
                ->sum(Db::raw('refund_balance_money * 100'));
            $kz_refund && $refund_actual_money = $refund_actual_money + $kz_refund;
            $wx_refund = WxRefundLogModel::query()
                ->where('order_no', $order->order_no)
                ->sum(Db::raw('refund_wx_money * 100'));
            $wx_refund && $refund_actual_money = $refund_actual_money + $wx_refund;
            if ($_refund = OrderRefundModel::query()->where('order_no', $order->order_no)->first()) {
                $refund->handle_status = $_refund['handle_type'];
                $refund->handle_status_cn = $this->handleStatus[$_refund['handle_type']];
                $refund->is_whole = $_refund['is_whole'];
                $refund->apply_money = round($_refund['refund_money'], 2);
            }
            if ($refund_actual_money > 0) {
                // 处理状态中文
                $refund->actual_money = round(($kz_refund + $wx_refund) / 100, 2);
                $refund->handle_status = 2;
                $refund->handle_status_cn = $this->handleStatus[2];
                $refund->is_whole = $refund->actual_money == $order['total_price'] ? 0 : 1;
            }
        }
        $data['goods_list'] = array_values($goods_list);
        $data['refund'] = $refund;
        return $this->success($data);
    }

    /**
     * 店铺营收
     * @param array $where
     * @return string
     */
    public static function storesIncome(array $where)
    {
        $totalMoney= OrderModel::where($where)->where('pay_at', '>',date('Y-m-d'))->sum('total_price');
//       if(empty($totalMoney)){
//           return $totalMoney;
//       }
        $_refundOrderNo = OrderRefundModel::where(['shop_id'=>$where['shop_id'],'status'=>Stakeholder::REFUND_COMPLETE])->where('refund_at', '>',date('Y-m-d'))->pluck('order_no');
        $totalRefundMoney = 0;
        if($_refundOrderNo){
            $refundOrderNo = $_refundOrderNo->toArray();
            $wxRefundMoney = WxRefundLogModel::whereIn('order_no',$refundOrderNo)->sum('refund_wx_money');
            $kzRefundMoney = KzRefundLogModel::whereIn('order_no',$refundOrderNo)->sum('refund_balance_money');
            $totalRefundMoney = bcadd((string)$wxRefundMoney,(string)$kzRefundMoney,2);
        }
        return bcsub((string)$totalMoney,(string)$totalRefundMoney,2);
    }
    /**
     * 通过店铺id获取店铺当天的收入
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function storesIncomes(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where(['shop_id' => $shop_id,'is_pay' => $type])
            ->selectRaw('COUNT(total_price) as count_income,SUM(total_price) as sum_income,ROUND(AVG(total_price)) as price,shop_id')
//            ->where(['pay_at' => date('Y-m-d', time())])
            ->whereDate('pay_at', date('Y-m-d', time()))
            ->first()
            ->toArray();
    }
    /**
     * 今日营收明细
     *
     * type为order 查询订单  为citic查询返款信息表
     * @param array $where
     * @param string $field
     * @return array
     */
    public static function storesIncomeDetail(array $where,string $field = '*', string $type=Stakeholder::FINANCE_ORDER)
    {

        if($type ==Stakeholder::FINANCE_ORDER){
            $detail =  OrderModel::selectRaw($field)
                ->where($where)
                ->groupBy(['is_pay'])
                ->get()->toArray();
        }else{
            $detail = CiticDataModel::where($where)
                ->where('create_time', '>',date('Y-m-d'))
                ->selectRaw($field)
                ->groupBy(['is_settlement'])
                ->get()->toArray();
        }
        return $detail;
    }
    /**
     * APP首页改版
     * @param int $shop_id
     * @return array
     */
    public function homeIndex(int $shop_id){
        //提示语
        $shopNameArr = ShopService::getInfoByShopId($shop_id);
        $time = date('H');
        if (5 <= (int)$time && (int)$time < 7){
            $prompt = '清晨打卡,'.$shopNameArr['shop_name'];
        }elseif(7 <= (int)$time && (int)$time < 9){
            $prompt = '早上好,'.$shopNameArr['shop_name'];
        }elseif (9 <= (int)$time && (int)$time < 12){
            $prompt = '上午好,'.$shopNameArr['shop_name'];
        }elseif (12 <= (int)$time && (int)$time < 14){
            $prompt = '中午好,'.$shopNameArr['shop_name'];
        }elseif (14 <= (int)$time && (int)$time < 18){
            $prompt = '下午好,'.$shopNameArr['shop_name'];
        }elseif (18 <= (int)$time && (int)$time < 19){
            $prompt = '傍晚好,'.$shopNameArr['shop_name'];
        }elseif (19 <= (int)$time && (int)$time < 24){
            $prompt = '晚上辛苦了,'.$shopNameArr['shop_name'];
        }elseif (24 == (int)$time){
            $prompt = '凌晨打卡,'.$shopNameArr['shop_name'];
        }elseif (0 <= (int)$time && (int)$time < 5){
            $prompt = '凌晨打卡,'.$shopNameArr['shop_name'];
        }
        //销售金额
        $amoutData = self::storesIncomes($shop_id,self::ORDER_IS_PAY_1);
        if(empty($amoutData['sum_income'])){
            $salesAmount = "0";
        }else{
            $salesAmount = $amoutData['sum_income'];
        }
        //上周今天销售金额
        $amount = OrderModel::query()
            ->where(['shop_id' => $shop_id,'is_pay' => 1])
            ->selectRaw('SUM(total_price) as sum_income,shop_id')
            ->whereDate('pay_at' , date('Y-m-d',strtotime('-1 week')))
            ->first()
            ->toArray();
        if(empty($amount['sum_income'])){
            $listAmount = "0";
        }else{
            $listAmount = $amount['sum_income'];
        }
        //差集
        $difference = $salesAmount - $listAmount;
        if ($difference<0){
            $diff = - $difference;
        }else{
            $diff = $difference;
        }
        //百分比
        if($listAmount == 0){
            $pct = 0;
        }else{
            $pct = round(($diff/$listAmount)*100);
        }
        if ($difference<0 && $listAmount != 0){
            $pct = - $pct;
        }
        $res = self::orderWidget($shop_id);
        //待核销订单总金额
        $notApplied=OrderModel::query()->whereRaw('status = 3 and order_type_status <> 1 and deal_type = 2')->where('shop_id', $shop_id)->selectRaw('SUM(total_price) as sum_income')->first()->toArray();
        //待退款订单总金额
        $notRefund = OrderRefundModel::query()->where(['shop_id'=>$shop_id,'handle_type'=>1])->selectRaw('SUM(refund_money) as money')->first()->toArray();
        //门店下所有团长的分拣商品总数
        $num = TeamLeaderService::sortingGoodsNumber($shop_id);
        //门店下所有团长的已分拣数量
        $sortingNum = TeamLeaderService::endSortingGoodsNumber($shop_id);
        //待分拣数量
        $notSortingNum = (int)$num - (int)$sortingNum;
        //待提交报货单
        $invoice = $res['order_status'] - $res['template_store'];
        if($invoice <0){
            $invoice = - $invoice;
        }
        // 当前时间的前24小时
        $start = date('YmdH', strtotime('-23 hours'));
        $end = date('YmdH');
        $ftime = date('Y-m-d H:i:s',strtotime('-23 hours'));
        $dateTime = date('Y-m-d H:i:s');
        $times = self::prTime($ftime,$dateTime);
        $timeRes = [];
        foreach ($times as $v){
            $timeRes[]['time'] = $v;
        }
        $arr = OrderModel::query()
            ->where(['shop_id'=>$shop_id,'is_pay'=> 1])
            ->whereRaw("DATE_FORMAT(pay_at,'%Y%m%d%H') > $start and DATE_FORMAT(pay_at,'%Y%m%d%H') <= $end")
            ->select([
                'shop_id',
                Db::raw('COUNT(1) as order_number'),
                Db::raw('SUM(total_price) as total_price'),
                Db::raw('GROUP_CONCAT(order_no) as order_nos'),
                Db::raw("DATE_FORMAT(pay_at,'%Y-%m-%d %H') as time")
            ])
            ->groupBy(['time'])
            ->get()
            ->toArray();
        $arrData = array_column($arr,null,'time');
        //排行TOP3
        $order_no =OrderModel::query()
            ->from('store_order_goods as g')
            ->join('store_order as s','s.order_no','=', 'g.order_no')
            ->where(['s.shop_id'=>$shop_id,'s.is_pay'=> 1])
            ->whereRaw("DATE_FORMAT(s.pay_at,'%Y%m%d%H') > $start and DATE_FORMAT(s.pay_at,'%Y%m%d%H') <= $end")
            ->select([
                'g.goods_id',
                'g.goods_title',
                Db::raw('SUM(g.selling_price) as selling_price'),
                Db::raw("DATE_FORMAT(s.pay_at,'%Y-%m-%d %H') as time"),
            ])
            ->groupBy(['time'],['g.goods_id'])
            ->get()
            ->toArray();
        $order = [];
        foreach ($order_no as $v){
            $order[$v['time']][] = $v;
        }
        $orderData = [];
        foreach ($order as $m=>$s){
            // 小于等于3个
            usort($s, function ($a, $b) {
                if ($a['selling_price'] == $b['selling_price']) {
                    return 0;
                }
                return ($a['selling_price'] < $b['selling_price']) ? 1: -1 ;
            });
            if(count($s)  <= 3){
                $orderData[$m] = $s;
                continue;
            }
            $orderData[$m] = array_slice($s,0,3);
        }
        foreach ($timeRes as $k => &$v){
            if (isset($arrData[$v['time']])) {
                $v['order_number'] = $arrData[$v['time']]['order_number'];
                $v['total_price'] = (string)$arrData[$v['time']]['total_price'];
            }else{
                $v['order_number'] = 0;
                $v['total_price'] = "0";
            }
        }
        foreach ($timeRes as $i => &$e){
            if (isset($orderData[$e['time']])) {
                $e['top'] = $orderData[$e['time']];
            }else{
                $e['top'] = [];
            }
        }
        $data = [
            'prompt' => $prompt,
            'amoutData' => $salesAmount,
            'amount' => $listAmount,
            'pct' => $pct,
            'notApplied' => $res['notApplied']?? "0",
            'notApplied_money' => $notApplied['sum_income']?? "0",
            'notRefund' => $res['notRefund']?? "0",
            'notRefund_money' => $notRefund['money']?? "0",
            'order_status' => $res['order_status']?? "0",
            'template_store' => $res['template_store']?? "0",
            'invoice' => $invoice ?? 0,
            'notSorting' => $res['notSortingNum']?? "0",
            'notSortingNum' => $notSortingNum ??0,
            'list' => $timeRes
        ];
        return $data;
    }
    /**
     * APP小组件
     * @param int $shop_id
     * @return array
     */
    public function orderWidget(int $shop_id){
        $time = date('Y-m-d H:i:s');
        $status = [2,4,6,7,8];
        //分子
        $order_status = WidgetModel::query()->where(['store_id'=>$shop_id])->whereDate('create_time' , date('Y-m-d'))->whereIn('order_status',$status)->count();
        //分母
        $template_store = TemplateWidgetModel::query()
            ->from('t_report_goods_template_store as s')
            ->leftJoin('t_report_goods_template as r','s.template_code','=','r.template_code')
            ->where(['s.store_id'=>$shop_id])
            ->where('r.start_time','<=',$time)
            ->where('r.end_time','>=',$time)
            ->count('s.id');
        //待核销
        $notApplied=OrderModel::query()->whereRaw('status = 3 and order_type_status <> 1 and deal_type = 2')->where('shop_id', $shop_id)->count();
        //团长待分拣
        $count = TeamLeaderService::notSortingGoodsNumber($shop_id);
        //待退款
        $notRefund = OrderRefundModel::query()->where(['shop_id'=>$shop_id,'handle_type'=>1])->groupBy()->count();
        $res = [
            'notApplied' => (string)$notApplied,
            'notRefund' => (string)$notRefund,
            'order_status' => (string)$order_status,
            'template_store' => (string)$template_store,
            'notSortingNum' => (string)$count
        ];
        return $res;
    }
    /**
     * 门店运营---销售对账--日预计计收入接口
     * @param int $shopId
     * @param string $times
     * @return array
     */
    public static function shopRevenue(int $shopId,string  $times)
    {
        // 当天总收入(微信+余额)
        $income = OrderModel::where(['shop_id'=>$shopId,'is_pay' => 1])
            ->whereDate('pay_at',$times)
            ->sum('total_price');
        // 储值退款
        $kz_refund_money = KzRefundLogModel::where(['shop_id' => $shopId])
            ->whereDate('create_time',$times)
            ->sum('refund_balance_money');
        // 微信退款
        $wx_refund_money = WxRefundLogModel::where(['shop_id' => $shopId])
            ->whereDate('create_time',$times)
            ->sum('refund_wx_money');
        // 微信支付收入
        $wechat_money = OrderModel::where(['shop_id'=>$shopId,'is_pay' => 1,'pay_type'=>1])
            ->whereDate('pay_at',$times)
            ->sum('total_price');
        // 储值收入
        $storage_money = OrderModel::where(['shop_id'=>$shopId,'is_pay' => 1,'pay_type'=>2])
            ->whereDate('pay_at',$times)
            ->sum('total_price');
        // 预计收入(微信+余额-退款)
        $projected_income = bcsub(bcsub((string)$income,(string)$kz_refund_money,2),(string)$wx_refund_money,2);// 预计收入
        $data = [
            'refund_money' => $projected_income,
            'wx_total_price' => $wechat_money ?? 0,
            'wx_refund_money' =>$wx_refund_money??0,
            'storage_total_price' => $storage_money ?? 0,
            'storage_need_money' => $kz_refund_money ?? 0,
        ];
        return $data;
    }
    /**
     * 门店运营---财务对账--线上明细--已打款列表
     *  type为order 查询订单  为citic查询返款信息表
     * @param array $where
     * @param string $start_time
     * @param int $page
     * @param int $perPage
     * @return array
     */
    public static function getOrderSerialNumByShopId(array $where, string $starTime,string $endTime, int $page, int $perPage, string $type = Stakeholder::FINANCE_ORDER)
    {
        if($type == Stakeholder::FINANCE_ORDER) {
            $list = OrderModel::where($where)
                ->whereBetween('pay_at', [$starTime, $endTime])
                ->selectRaw('is_pay,sum(total_price) sum_money,DATE_FORMAT(pay_at,"%Y-%m-%d") as yesat')
                ->groupBy(['yesat'])
                ->orderBy('yesat', 'desc')
                ->forPage($page, $perPage)
                ->get();
            $count = OrderModel::where($where)
                ->whereBetween('pay_at', [$starTime, $endTime])
                ->selectRaw('is_pay,sum(total_price) sum_money,DATE_FORMAT(pay_at,"%Y-%m-%d") as yesat')
                ->groupBy(['yesat'])
                ->orderBy('yesat', 'desc')
                ->get()->count();
        }else{
            $list = CiticDataModel::where($where)
                ->whereBetween('create_time', [$starTime, $endTime])
                ->selectRaw('is_settlement,sum(real_price) sum_money,DATE_FORMAT(create_time,"%Y-%m-%d") as yesat')
                ->groupBy(['yesat'])
                ->orderBy('yesat', 'desc')
                ->forPage($page, $perPage)
                ->get();
            $count = CiticDataModel::where($where)
                ->whereBetween('create_time', [$starTime, $endTime])
                ->selectRaw('is_settlement,sum(real_price) sum_money,DATE_FORMAT(create_time,"%Y-%m-%d") as yesat')
                ->groupBy(['yesat'])
                ->orderBy('yesat', 'desc')
                ->get()->count();
        }
        return ['count'=>$count,'data'=>$list->toArray()];
    }
    /**
     * 门店运营---销售对账--历史账单列表信息
     * @param $where
     * @param $page
     * @param $perPage
     * @return array
     */
    public static function storestoGroupTimeIncome(array $where,int $page, int $perPage)
    {
        $list = OrderModel::where($where)
            ->selectRaw('is_pay,sum(total_price) sum_money,DATE_FORMAT(pay_at,"%Y-%m-%d") as yesat')
            ->groupBy(['yesat'])
            ->orderBy('yesat', 'desc')
            ->forPage($page, $perPage)
            ->get();
        $count = OrderModel::where($where)
            ->selectRaw('is_pay,sum(total_price) sum_money,DATE_FORMAT(pay_at,"%Y-%m-%d") as yesat')
            ->groupBy(['yesat'])
            ->orderBy('yesat', 'desc')
            ->get()->count();
        return ['count'=>$count,'data'=>$list->toArray()];
    }
    /**
     * 门店运营---销售对账--历史账单---当日订单明细
     * @param array $where
     * @param string $times
     * @param int $perPage
     * @param string $field
     * @return array
     */
    public static function storestIncomeByTime(array $where,string $times,int $perPage,string $field = '*')
    {
        $list = OrderModel::selectRaw($field)->where($where)
            ->whereDate('pay_at', $times)
            ->orderBy('pay_at', 'desc')
            ->paginate($perPage);
        $orderNoArr = array_column($list->items(),'order_no');
        $_wxRefundMoney = WxRefundLogModel::whereIn('order_no',$orderNoArr)->groupBy(['order_no'])->selectRaw('order_no,sum(refund_wx_money) as refund_wx_money')->get()->toArray();
        $_storageNeedMoney = KzRefundLogModel::whereIn('order_no',$orderNoArr)->groupBy(['order_no'])->selectRaw('order_no,sum(refund_balance_money) as storage_need_money')->get()->toArray();
        $wxRefundMoney = array_column($_wxRefundMoney,'refund_wx_money','order_no');
        $storageNeedMoney = array_column($_storageNeedMoney,'storage_need_money','order_no');
        foreach ($list as $k=> $v){
            if ($v['deal_type'] == Stakeholder::ORDER_TYPE_NORMAL_SELF) {
                $list[$k]['status_name'] = "自提订单";
            } else {
                $list[$k]['status_name'] = "配送订单";
            }
            if ($v['pay_type'] == Stakeholder::PAYMENT_METHOD_WECHAT) {
                $list[$k]['wx_total_price'] = $v['total_price'] ?? 0;
                $list[$k]['storage_total_price'] = 0;
            } else {
                $list[$k]['wx_total_price'] = 0;
                $list[$k]['storage_total_price'] = $v['total_price'] ?? 0;
            }
            $list[$k]['freight_price'] = $v['freight_price'] - $v['coupon_freight_cut'];
            $list[$k]['refund_wx_money'] = $wxRefundMoney[$list[$k]['order_no']] ?? 0;
            $list[$k]['storage_need_money'] = $storageNeedMoney[$list[$k]['order_no']] ?? 0;
        }
        return ['count'=>$list->total(),'data'=>$list->items()];
    }
    /**
     * 售后单订单号列表
     *
     * @param array $where
     * @return array
     */
    public function refundOrderNos($where = [])
    {
        $refund_nos = OrderRefundModel::query()->where($where)->select('order_no')->get();
        return $refund_nos ? $refund_nos->toArray() : [];
    }
    /**
     * 搜索订单条件
     *
     * @param $shop_id
     * @param $content
     * @return array
     */
    public function searchWhere($shop_id, $content)
    {
        if (preg_match("/1[23456789]{1}\d{9}$/", $content)) {
            $mid = MemberModel::query()->where('phone', 'like', "%$content%")->value('mid');
            if (!$mid) {
                return ['order_no' => null];
            }
            $where = ['shop_id' => $shop_id, 'mid' => $mid];
        } else {
            $where = ['shop_id' => $shop_id, 'order_no' => $content];
        }
        return $where;
    }
    /**
     * 批量发货
     *
     * @param array $order_nos
     * @return array
     */
    public function bulkShipping(array $order_nos)
    {
        $updateArr = [];
        $orders = OrderModel::query()->whereIn('order_no', $order_nos)->get(['order_no', 'order_type']);
        foreach ($orders as $order) {
            $_update['order_no'] = $order->order_no;
            $_update['status'] = 3;
            if ($order->order_type == 6) {
                $_update['order_type_status'] = 2;
            }
            $updateArr[] = $_update;
        }
        $ret = $this->updateBatch('store_order', $updateArr);
        if (!$ret) {
            return $this->error(ErrorCode::NOT_IN_FORCE);
        }
        return $this->success();
    }
    /**
     * 批量更新
     *
     * @param $tableName
     * @param array $multipleData
     * @return false|int
     */
    public function updateBatch($tableName, $multipleData = [])
    {
        try {
            if (empty($multipleData)) {
                throw new \Exception("数据不能为空");
            }
            $firstRow = current($multipleData);

            $updateColumn = array_keys($firstRow);
            $referenceColumn = isset($firstRow['id']) ? 'id' : current($updateColumn);
            unset($updateColumn[0]);
            $updateSql = "UPDATE " . $tableName . " SET ";
            $sets = [];
            $bindings = [];
            foreach ($updateColumn as $uColumn) {
                $setSql = "`" . $uColumn . "` = CASE ";
                foreach ($multipleData as $data) {
                    $setSql .= "WHEN `" . $referenceColumn . "` = ? THEN ? ";
                    $bindings[] = $data[$referenceColumn];
                    $bindings[] = $data[$uColumn];
                }
                $setSql .= "ELSE `" . $uColumn . "` END ";
                $sets[] = $setSql;
            }
            $updateSql .= implode(', ', $sets);
            $whereIn = collect($multipleData)->pluck($referenceColumn)->values()->all();
            $bindings = array_merge($bindings, $whereIn);
            $whereIn = rtrim(str_repeat('?,', count($whereIn)), ',');
            $updateSql = rtrim($updateSql, ", ") . " WHERE `" . $referenceColumn . "` IN (" . $whereIn . ")";
            return DB::update($updateSql, $bindings);
        } catch (\Exception $e) {
            return false;
        }
    }
    /**
     * 通过店铺id获取店铺本月的收入
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function currentMonth(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where(['shop_id' => $shop_id,'is_pay' => $type])
            ->selectRaw('SUM(total_price) as month_sum,COUNT(total_price) as month_count')
            ->whereMonth('pay_at', date('m', time()))
            ->first()
            ->toArray();

    }
    /**
     * 平均价格
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function avgPrice(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where([['shop_id','=',$shop_id],['is_pay','=',$type],['status','<>',5]])
            ->whereDate('pay_at', date('Y-m-d', time()))
            ->avg('total_price');
    }
    /**
     * 通过店铺id获取店铺获取流程图信息
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function monthMoneySum(int $shop_id,int $type)
    {
        return OrderModel::query()
            ->where([['shop_id','=',$shop_id],['is_pay','=', $type]])
            ->selectRaw('shop_id,SUM(total_price) as month_sum_income,COUNT(total_price) as month_count_income,CONCAT(YEAR(pay_at),"-",MONTH(pay_at)) as releaseYearMonth')
            ->groupBy('releaseYearMonth')
            ->get()
            ->toArray();
    }
    /**
     * 通过店铺id获取店铺获取流程图信息
     * @param int $shop_id
     * @param int $type
     * @return array|string
     */
    public function monthMoneySums(int $shop_id,int $type)
    {
        $time = date('Y');
        $res = OrderModel::query()
            ->where([['shop_id', '=' ,$shop_id],['is_pay' ,'=', $type],['pay_at','>=', (string)$time]])
            ->selectRaw('shop_id,SUM(total_price) as month_sum_income,COUNT(total_price) as month_count_income,CONCAT(YEAR(pay_at),"-",MONTH(pay_at)) as releaseYearMonth')
            ->groupBy('releaseYearMonth')
            ->get()
            ->toArray();
        $StoreOrderRefundMonthMoney = OrderRefundService::refundAmountMonth($shop_id);
        $array = [];
        $data_count = [];
        foreach ($res as $k=>$v){
            $arr[substr($v['releaseYearMonth'], 5)] = $v['month_sum_income'] - $StoreOrderRefundMonthMoney;
            $data[substr($v['releaseYearMonth'], 5)] = $v['month_count_income'];
        }
        for($i=1; $i <=12; $i++){
            if(isset($i,$arr[$i])){
                $array[$i] = $arr[$i];
                $data_count[$i] = $data[$i];
            }else{
                $array[$i] = 0;
                $data_count[$i] = 0;
            }
        }
        $datas['price'] = $array;
        $datas['count'] = $data_count;
        return $datas;
    }

    /**
     * 根据订单号获取订单商品购买列表
     *
     * @param $order_no
     * @return array
     */
    public function getOrderGoodsList($order_no)
    {
        $filed = [
            "goods_title",
            "goods_spec",
            "goods_logo",
            "number",
            "selling_price",
            "goods_dis_price",
            "deductMoney",
        ];
        $data = OrderGoodsModel::query()->select($filed)->where('order_no', $order_no)->get();
        return $this->success($data);
    }
    /**
     * 订单核销
     * @param $shop_id
     * @param $write_off_code
     * @return array
     */
    public function writeOff($shop_id, $write_off_code)
    {
        try {
            $order = OrderModel::query()->where('write_off_code', $write_off_code)->first();
            if (!$order) {
                throw new \Exception('不存在', ErrorCode::NOT_EXIST);
            }
            if ($order->shop_id != $shop_id) {
                throw new \Exception('权限不足', 403);
            }
            if ($order->write_off_code_status == 2) {
                throw new \Exception('请勿重复核销', ErrorCode::NOT_IN_FORCE);
            }
            if (strtotime($this->standardDate($order['appointment_time'])) > time()) {
                throw new \Exception('不能提前核销', ErrorCode::NOT_IN_FORCE);
            }
            $res = $order->update(['write_off_code_status' => 2, 'status' => 4]);
            if (!$res) {
                throw new \Exception('核销失败', ErrorCode::NOT_IN_FORCE);
            }
            return $this->success();
        } catch (\Exception $e) {
            return $this->error($e->getCode(), $e->getMessage());
        }
    }
    /**
     * 拒绝退款
     *
     * @param $order_no
     * @return array
     */
    public function refuseRefund($order_no)
    {
        try {
            $info = $this->orderFind(['order_no' => $order_no], false);
            if (!$info) {
                throw new \Exception('找不到此订单', ErrorCode::NOT_EXIST);
            }
            $refund = OrderRefundModel::query()->where('order_no', $order_no)->first(['refund_no', 'order_no', 'before_status']);
            if (!$refund) {
                throw new \Exception('不存在的退款订单', ErrorCode::NOT_EXIST);
            }
            $res1 = OrderRefundModel::query()->where('order_no', $order_no)->update([
                'status'      => 1,
                'handle_type' => 2,
                'refund_at'   => date('Y-m-d H:i:s', time()),
            ]);
            if (!$res1) {
                throw new \Exception('保存退款表失败', ErrorCode::NOT_IN_FORCE);
            }
            $res2 = $info->update(['status' => $refund['before_status']]);
            if (!$res2) {
                throw new \Exception('更改订单状态失败', ErrorCode::NOT_IN_FORCE);
            }
        } catch (\Exception $e) {
            return $this->error($e->getCode(), $e->getMessage());
        }
        return $this->success();
    }
    /**
     * 获取订单数量
     * @param $shop_id
     * @return array
     */
    public function getOrderCount($shop_id)
    {
        $func = function ($where) use ($shop_id) {
            return OrderModel::query()->whereRaw($where)->where('shop_id', $shop_id)->count();
        };
        // 待发货
        $waiting_ship = $func('status = 2 and order_type_status <> 2');
        // 配送中
        $in_delivery = $func('status = 3 and order_type_status <> 2 and deal_type = 1');
        // 待自提
        $waiting_take = $func('status = 3 and order_type_status <> 1 and deal_type = 2');
        // 用户售后申请退款单
        $refund = $func('status = 7');
        return $this->success(compact('waiting_ship', 'in_delivery', 'waiting_take', 'refund'));
    }
    /**
     * 获取订单商品列表
     */
    public function getAfterSaleOrderGoods($order,$order_no){
        $goodsList = $order->goods()->where(['order_no' => $order_no])->select([
            'id',
            'goods_id',
            'goods_title',
            'goods_spec',
            'goods_logo',
            Db::raw('number - IFNULL(refund_number,0) - IFNULL(shop_refund_number,0) as number'),
            'selling_price',
            'goods_dis_price',
            'deductMoney',
        ])->having('number', '>', 0)->get();
        return $goodsList;
    }

    public function getPosPrice(int $shop_id, array $goods){
        $lsy_shop_no = ShopModel::query()->where('shop_id', $shop_id)->value('lsy_shop_no');
        $pos_price = $this->container->get(LsyShopGoodsPriceService::class)
            ->shopGoodsPriceByScheme($lsy_shop_no, array_column($goods,'goods_crm_code'));
        $pos_price_arr = collect($pos_price)->keyBy('crm_goods_id')->toArray();
        array_walk($goods, function(&$item) use ($pos_price_arr){
            if ($item['read_pos_price'] == 1){
                $posSellingPrice = array_key_exists($item['goods_crm_code'], $pos_price_arr) ?
                    $pos_price_arr[$item['goods_crm_code']]['price'] : $item['unit_price'];
            }else{
                $posSellingPrice = $item['unit_price'];
            }
            $item['unit_price'] = $item['scant_id'] == 1 ?
                bcmul(bcdiv($posSellingPrice,'1000',6),(string)$item['ratio'],2) : $posSellingPrice;
        });
        return $goods;
    }

    public function createEntrustOrder(int $shop_id, string $phone, array $goods, array $params){
        try {
            $goodsArr = array_column($goods, null, 'goods_id');
            $extInfo = GoodsModel::query()
                ->from('store_goods as g')
                ->leftJoin('store_goods_list as gl', 'g.id', '=', 'gl.goods_id')
                ->select(['gl.goods_id','g.group_id','g.scant_id','g.ratio','g.kz_type_id','g.kz_goods_id','g.read_pos_price','g.read_pos_stock',
                    'g.logo','g.title','g.goods_crm_code','gl.goods_pick_time','gl.goods_spec as spec','gl.price_selling as unit_price'])
                ->whereIn('g.id', array_keys($goodsArr))->get()->toArray();
            if($params['order_source'] == 0) $extInfo =  $this->getPosPrice($shop_id, $extInfo);
            foreach ($extInfo as $k => $item) {
                $extInfo[$k]['number'] = $goodsArr[$item['goods_id']]['number']; // 数量
                $extInfo[$k]['subtotal'] = bcmul($extInfo[$k]['number'], $item['unit_price'], 2); // 原合计
                if ($params['discount'] > 0){
                    $extInfo[$k]['dis_unit_price'] = $goodsArr[$item['goods_id']]['dis_unit_price']; //优惠后单价
//                    $extInfo[$k]['dis_subtotal'] = bcmul($extInfo[$k]['number'], $extInfo[$k]['dis_unit_price'], 2); //优惠后合计
                    $extInfo[$k]['dis_subtotal'] = $goodsArr[$item['goods_id']]['dis_subtotal'];
                }else{
                    $extInfo[$k]['dis_unit_price'] = $item['unit_price'];
                    $extInfo[$k]['dis_subtotal'] = $extInfo[$k]['subtotal'];
                }
                $extInfo[$k]['kz_self_num'] = Str::random();
            }
            Db::transaction(function () use ($shop_id, $phone, $params, $extInfo) {
                $amount = array_sum(array_column($extInfo, 'subtotal'));
                $entrust = EntrustOrderModel::create([
                    'shop_id' => $shop_id,
                    'phone' => $phone,
                    'amount' => $amount,//原总价
                    'dis_amount' => bcsub((string)$amount, $params['discount'], 2),// 优惠后总价
                    'discount' => $params['discount'],
                    'status' => 0,
                    'goods' => is_array($params['goods_list']) ? json_encode($params['goods_list']) : $params['goods_list'],
                    'order_source' => $params['order_source'],
                ]);
                $share = $this->getShareInfo($entrust, 'create');
                $entrust->share = json_encode($share);
                $entrust->save();
                Context::set('share', $share);
                $extInfo = array_map(fn($v) => ['entrust_order_id' => $entrust->id] + $v, $extInfo);
                EntrustOrderGoodsModel::query()->insert($extInfo);
            });
        }catch (\Exception $e){
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $e->getMessage()];
        }
        $this->container->get(CartBusinessService::class)->clearPreset([1,2][$params['order_source']]);
        return ['code' => 1, 'msg' => '提交成功', 'data' => Context::get('share')];
    }

    protected function getShareInfo(object $entrust, string $event){
        $exp = strtotime(date('Y-m-d', strtotime('+1 day')));
        $path = $entrust->order_source==1?"pages/follow-order-sure/follow-order-sure":"pages/order-sure/order-sure";
        $filePath = 'https://'. env('OSS_BUCKET') . '.'  . env('OSS_ENDPOINT') . '/' . env('OSS_DIR');
        $thumb = $event == 'create' ?
            $this->container->get(Generator::class)->generateEntrustOrderSharePic($entrust->dis_amount,$entrust->id):
            "{$filePath}/entrust-share-{$entrust->id}.jpg";
        return [
            'path' => "{$path}?entrust_order_id={$entrust->id}&exp={$exp}",
            'title' => '您有一个待支付订单等您支付',
            'thumb' => $thumb,
        ];
    }

    public function getTheUnpaidEntrustOrder(int $shop_id, string $phone, $perpage){
        $where = ['shop_id' => $shop_id, 'phone' => $phone, 'status' => 0];
        return EntrustOrderModel::query()
            ->with('goods:entrust_order_id,goods_id,logo,number')
            ->selectRaw('id,case order_source when 0 then "及时达" else "次日达" end as source_name,dis_amount as total_price,"待付款" as status_name,created_at as date')
            ->where($where)
            ->latest('date')
            ->paginate((int)$perpage);
    }

    public function getTheCompletedEntrustOrder(int $shop_id, string $phone, $perpage, ?string $keyword){
        $where = ['shop_id' => $shop_id, 'platform_type' => 3, 'entrust_phone' => $phone];
        $status = [Stakeholder::ORDER_PENDING_SHIP,Stakeholder::ORDER_PENDING_PICK,Stakeholder::ORDER_RECEIVED];
        return OrderModel::query()
            ->with('goods:order_no,goods_id,goods_logo as logo,number')
            ->selectRaw('order_no,total_price,"已完成" as status_name,case order_source when 0 then "及时达" else "次日达" end as source_name,create_at as date')
            ->where($where)
            ->whereIn('status', $status)
            ->when($keyword, function ($query, $keyword) {
                if(strlen(trim($keyword)) <= 11){
                    return $query->where('order_phone', $keyword);
                }
                return $query->where('order_no', $keyword);
            })
            ->latest('date')
            ->paginate((int)$perpage);
    }

    public function getTheRefundEntrustOrder(int $shop_id, string $phone, $perpage, ?string $keyword){
        $where = [
            'refund.shop_id' => $shop_id,
            'refund.entrust_phone' => $phone,
            'order.shop_id' => $shop_id,
            'order.platform_type' => 3,
            'order.entrust_phone' => $phone,
        ];
//        $order = OrderRefundModel::query()
//            ->from('store_order_refund as refund')
//            ->leftJoin('store_order as order', 'refund.order_no', '=', 'order.order_no')
////            ->with('goods:refund_no,goods_id,goods_logo as logo,refund_number as number')
//            ->selectRaw('refund.order_no,refund.refund_no,case refund.order_source when 0 then "及时达" else "次日达" end as source_name,refund.refund_money,order.total_price,refund.create_at as date,case refund.status when 0 then "退款处理中" when 1 then "已驳回" else "已退款" end as status_name')
//            ->where($where)
//            ->when($keyword, function ($query, $keyword) {
//                return $query->where('order.order_phone', $keyword)
//                    ->orWhere('order.order_no', $keyword);
//            })
//            ->latest('date')
//            ->paginate((int)$perpage);

        return OrderModel::query()
            ->from('store_order as order')
            ->rightJoin('store_order_refund as refund','order.order_no', '=', 'refund.order_no')
            ->with('goods:order_no,goods_id,goods_logo as logo,number')
            ->selectRaw('refund.order_no,refund.refund_no,case refund.order_source when 0 then "及时达" else "次日达" end as source_name,refund.refund_money,order.total_price,refund.create_at as date,case refund.status when 0 then "退款处理中" when 1 then "已驳回" else "已退款" end as status_name')
            ->where($where)
            ->when($keyword, function ($query, $keyword) {
                if(strlen(trim($keyword)) <= 11){
                    return $query->where('order.order_phone', $keyword);
                }
                return $query->where('order.order_no', $keyword);
            })
            ->latest('date')
            ->paginate((int)$perpage);
    }


    public function getAllEntrustOrder(int $shop_id, string $phone, $perpage){
        $ret1 = collect($this->getTheUnpaidEntrustOrder($shop_id, $phone, $perpage)->items())->toArray();
        $ret2 = collect($this->getTheCompletedEntrustOrder($shop_id, $phone, $perpage, null)->items())->toArray();
        $ret3 = collect($this->getTheRefundEntrustOrder($shop_id, $phone, $perpage, null)->items())->toArray();
        return array_values(collect(array_merge($ret1, $ret2, $ret3))->sortByDesc('date')->toArray());
    }


    public function getEntrustOrderDetail(array $where, array $field){
        $detail = EntrustOrderModel::query()
            ->with('goods:entrust_order_id,goods_id,title,spec,logo,number,unit_price,dis_unit_price,subtotal,dis_subtotal,goods_pick_time')
            ->select($field)
            ->where($where)
            ->first();
        if($detail && $detail->order_source == 1) {
            $takeDate = $this->getOverNightTakeDate();
            foreach ($detail->goods as $item) {
                $item->goods_pick_time = $takeDate . ' ' . substr($item->goods_pick_time, 0, 5);
            }
        }
        return $detail;
    }

    public function restartPayment(array $where, array $field){
        $entrust = EntrustOrderModel::query()->where($where)->select($field)->first();
        if ($entrust){
            $share = $this->getShareInfo($entrust, 'restart');
            $entrust->share = json_encode($share);
            $entrust->save();
        }
        return $share ?? [];
    }

    public function updateEntrust(array $where, array $update){
        return EntrustOrderModel::query()->where($where)->update($update);
    }

}
